package up6.model;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import up6.PathTool;
import up6.biz.FileEtag;
import up6.biz.FolderSchema;

import java.io.*;
import java.util.*;

/*
 * 原型
 * 更新记录：
 * 	2016-01-07
 * 		FileMD5更名为md5
 * 		PostComplete更名为complete
 * 		FileLength更名为lenLoc
 * 		FileSize更名为sizeLoc
 * 		PostedPercent更名为perSvr
*/
public class FileInf {

	public FileInf()
	{		
	}

	public String id="";
	public String pid="";
    public String pidRoot="";	
	/**	 * 表示当前项是否是一个文件夹项。	 */
	public boolean fdTask=false;		
	//	/// 是否是文件夹中的子文件	/// </summary>
	public boolean fdChild=false;
	/**	 * 用户ID。与第三方系统整合使用。	 */
	public int uid=0;
	/**	 * 文件在本地电脑中的名称	 */
	public String nameLoc="";
	/**	 * 文件在服务器中的名称。	 */
	public String nameSvr="";
	/**	 * 文件在本地电脑中的完整路径。示例：D:\Soft\QQ2012.exe	 */
	public String pathLoc="";	
	/**	 * 文件在服务器中的完整路径。示例：F:\\ftp\\uer\\md5.exe	 */
	public String pathSvr="";
	/**	 * 文件在服务器中的相对路径。示例：/www/web/upload/md5.exe	 */
	public String pathRel="";
	/**	 * 文件MD5	 */
	public String md5="";
	/**	 * 数字化的文件长度。以字节为单位，示例：120125	 */
	public long lenLoc=0;
    /**
     * 加密后的文件大小
     */
    public long lenLocSec = 0;
	/**	 * 格式化的文件尺寸。示例：10.03MB	 */
	public String sizeLoc="";
	/**	 * 文件续传位置。	 */
	public long offset=0;
	/**	 * 已上传大小。以字节为单位	 */
	public long lenSvr=0;
	/**	 * 已上传百分比。示例：10%	 */
	public String perSvr="0%";
	public boolean complete=false;
	public Date PostedTime = new Date();
	public boolean deleted=false;
	/**	 * 是否已经扫描完毕，提供给大型文件夹使用，大型文件夹上传完毕后开始扫描。	 */
	public boolean scaned=false;
	//块索引，基于1
	public int blockIndex=0;
	//块偏移,基于整个文件
	public long blockOffset=0;
	public int blockSize=0;
	//文件块总数
	public int blockCount=0;
	public boolean encrypt=false;
	//FastDFS.id
	public String fastdfs_id="";
	//Minio.id
	public String minio_id="";
	//
	public String etag="";

	/// <summary>
	/// 计算文件加密后的大小，16字节对齐
	/// </summary>
	public void calLenLocSec() {
		long a = this.lenLoc % 16;
		this.lenLocSec = this.lenLoc + (16 - (a > 0 ? a : 16));
	}
	
	public String schemaFile() {
		return this.parentDir().concat("/schema.txt");
	}
	
	/**
	 * 生成AWS S3文件key
	 * D:\Soft\guid\QQ.exe => /guid/QQ.exe
	 * @return
	 */
	public String S3Key() {    	
    	//格式 /guid/QQ.exe
    	String key = PathTool.combin("", this.id);
    	key = PathTool.combin(key, this.nameLoc);
    	return key;
	}
	
	/**
	 * 返回AWS s3，ETag保存文件
	 * 路径：dir/guid/etags.txt
	 * @return
	 */
	public String ETagsFile() {
		String f = PathTool.combin(this.parentDir(),this.id);
		f = PathTool.combin(f,"etags.txt");
		return f;
	}

	public String parentDir()
	{
		File f = new File(this.pathSvr);
		return f.getParent().replace('\\', '/');
	}

	//保存到层级信息文件中
	public void saveScheme()
	{
		//System.out.println("FileInf.saveScheme,块索引："+String.valueOf(this.blockIndex));
		//仅第一块保存数据
		if (1 != this.blockIndex ) return;

		//不是子文件=>退出
		if (StringUtils.isEmpty(this.pid) ) return;

		//保存子文件数据
		FolderSchema fs = new FolderSchema();
		this.calLenLocSec();//自动计算文件加密后的大小
		fs.addFile(this);
	}
	
	/**
	 * 保存块ID信息
	 * 路径：
	 * D:/Soft/guid/etags.txt
	 */
	public void saveEtags() {
		FileEtag fe = new FileEtag();
		fe.saveTags(this);
	}
	
	/**
	 * <CompleteMultipartUpload xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
	   <Part>
	      <ChecksumCRC32>string</ChecksumCRC32>
	      <ChecksumCRC32C>string</ChecksumCRC32C>
	      <ChecksumSHA1>string</ChecksumSHA1>
	      <ChecksumSHA256>string</ChecksumSHA256>
	      <ETag>string</ETag>
	      <PartNumber>integer</PartNumber>
	   </Part>
	   ...
	</CompleteMultipartUpload>

	 * @return
	 */
	public String etags() {
		String xml = "";
		List<FileInf> files = new ArrayList<FileInf>();
		//加载/guid/etags.txt
		File f = new File(this.ETagsFile());
		BufferedReader br;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(f),"UTF-8"));
			String line = null;
			Gson g = new Gson();
			Map<Integer,Boolean> blocks = new HashMap<Integer, Boolean>();
			while( (line = br.readLine() )!=null )
			{
				FileInf block = g.fromJson(line, FileInf.class);
				if(!blocks.containsKey(block.blockIndex))
				{
					files.add(block);
					blocks.put(block.blockIndex,true);
				}
			}
			br.close();
			
		    Document dom = DocumentHelper.createDocument();
		    Element root = dom.addElement("CompleteMultipartUpload");
		    for(FileInf i : files)
		    {
		    	Element part = root.addElement("Part");
		    	part.addElement("ETag").addText(i.etag);
		    	part.addElement("PartNumber").addText( String.valueOf( i.blockIndex ));
		    }
		    xml = root.asXML();

		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return xml;
	}
	
	public String toJson() {
		Gson g = new Gson();
		return g.toJson(this);
	}
}